package cn.topcodes.tcsf.wechat.service;

import cn.topcode.unicorn.utils.UuidUtil;
import cn.topcode.unicorn.wxsdk.WXContext;
import cn.topcode.unicorn.wxsdk.account.dto.ActionInfo;
import cn.topcode.unicorn.wxsdk.account.dto.CreateTicketResult;
import cn.topcode.unicorn.wxsdk.account.dto.ReqCreateTicket;
import cn.topcode.unicorn.wxsdk.account.dto.Scene;
import cn.topcode.unicorn.wxsdk.base.WXResponseCode;
import cn.topcodes.tcsf.admin.commons.generic.GenericService;
import cn.topcodes.tcsf.wechat.domain.entity.WechatInvite;
import cn.topcodes.tcsf.wechat.domain.entity.WechatMp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;

/**
 * 微信邀请服务实现
 * @author Unicorn
 * @date 2017/12/10
 */
@Component
public class WechatInviteServiceImpl extends GenericService<WechatInvite> implements WechatInviteService {

    @Autowired
    private WechatMpService wechatMpService;

    /**
     * 获取临时邀请二维码内容
     *
     * @param expiredSeconds 过期秒数
     * @param wechatUserId   微信用户ID
     * @return 二维码内容
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public String getInviteQrCodeContent(String mpId, long expiredSeconds, Long wechatUserId, String params) {
        return this.getInvite(mpId, expiredSeconds, wechatUserId, params).getQrcodeContent();
    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public String getInviteQrCodeContent(long expiredSeconds, Long wechatUserId, String params) {
        return getInviteQrCodeContent(wechatMpService.getDefaultMpId(), expiredSeconds, wechatUserId, params);
    }

    @Override
    public WechatInvite findInvite(Long wechatUserId, String params) {
        Example example = this.buildExample();
        example.or().andEqualTo(WechatInvite.FIELD_TYPE, WechatInvite.TYPE_TEMP)
                .andEqualTo(WechatInvite.FIELD_WECHAT_USER_ID, wechatUserId)
                .andEqualTo(WechatInvite.FIELD_PARAMS, params);
        return this.findOne(example);
    }

    /**
     * 获取临时邀请
     *
     * @param expiredSeconds 过期秒数
     * @param wechatUserId   微信用户ID
     * @param params         参数
     * @return 临时邀请信息
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public WechatInvite getInvite(String mpId, long expiredSeconds, Long wechatUserId, String params) {
        WechatInvite wechatInvite = this.findInvite(wechatUserId, params);
        if(wechatInvite == null || isExpired(wechatInvite)) {
            String senceStr = null;
            if(wechatInvite == null) {
                senceStr = UuidUtil.getUUID();
            }else {
                senceStr = wechatInvite.getSenceStr();
            }
            CreateTicketResult result = getTicket(mpId, expiredSeconds, ReqCreateTicket.ACTION_QR_STR_SCENE, senceStr);
            String content = result.getUrl();
            String ticket = result.getTicket();

            if(wechatInvite == null) {
                wechatInvite = new WechatInvite();
            }
            wechatInvite.setType(WechatInvite.TYPE_TEMP);
            wechatInvite.setQrcodeContent(content);
            wechatInvite.setTime(new Date());
            wechatInvite.setWechatUserId(wechatUserId);
            wechatInvite.setSenceStr(senceStr);
            wechatInvite.setExpiredSeconds(result.getExpireSeconds());
            wechatInvite.setTicket(ticket);
            wechatInvite.setParams(params);
            WechatMp wechatMp = wechatMpService.findWechatMpByMpId(mpId);
            wechatInvite.setWechatMpId(wechatMp.getId());
            this.save(wechatInvite);
        }
        return wechatInvite;
    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public WechatInvite getInvite(long expiredSeconds, Long wechatUserId, String params) {
        return getInvite(wechatMpService.getDefaultMpId(), expiredSeconds, wechatUserId, params);
    }


    /**
     * 获取永久邀请二维码内容
     * @param wechatUserId   微信用户ID
     * @return 二维码内容
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public String getLimitInviteQrCodeContent(String mpId, Long wechatUserId, String params) {
        return this.getLimitInvite(mpId, wechatUserId, params).getQrcodeContent();
    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public String getLimitInviteQrCodeContent(Long wechatUserId, String params) {
        return getLimitInviteQrCodeContent(wechatMpService.getDefaultMpId(), wechatUserId, params);
    }

    @Override
    public WechatInvite findLimitInvite(Long wechatUserId, String params) {
        Example example = this.buildExample();
        example.or().andEqualTo(WechatInvite.FIELD_TYPE, WechatInvite.TYPE_FOREVER)
                .andEqualTo(WechatInvite.FIELD_WECHAT_USER_ID, wechatUserId)
                .andEqualTo(WechatInvite.FIELD_PARAMS, params);
        return this.findOne(example);
    }

    /**
     * 获取永久邀请信息
     *
     * @param wechatUserId 微信用户ID
     * @param params       参数
     * @return 永久邀请信息
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public WechatInvite getLimitInvite(String mpId, Long wechatUserId, String params) {
        WechatInvite wechatInvite = this.findLimitInvite(wechatUserId, params);
        if(wechatInvite == null) {
            String senceStr = UuidUtil.getUUID();
            CreateTicketResult result = getTicket(mpId,30, ReqCreateTicket.ACTION_QR_LIMIT_STR_SCENE, senceStr);
            String content = result.getUrl();
            String ticket = result.getTicket();
            wechatInvite = new WechatInvite();
            wechatInvite.setType(WechatInvite.TYPE_FOREVER);
            wechatInvite.setQrcodeContent(content);
            wechatInvite.setTime(new Date());
            wechatInvite.setWechatUserId(wechatUserId);
            wechatInvite.setSenceStr(senceStr);
            wechatInvite.setTicket(ticket);
            wechatInvite.setParams(params);
            WechatMp wechatMp = wechatMpService.findWechatMpByMpId(mpId);
            wechatInvite.setWechatMpId(wechatMp.getId());
            this.create(wechatInvite);
        }
        return wechatInvite;
    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public WechatInvite getLimitInvite(Long wechatUserId, String params) {
        return getLimitInvite(wechatMpService.getDefaultMpId(), wechatUserId, params);
    }

    /**
     * 通过场景值获取邀请信息
     *
     * @param senceStr 场景值
     * @return 邀请信息
     */
    @Override
    public WechatInvite findBySenceStr(String senceStr) {
        Example example = this.buildExample();
        example.or().andEqualTo(WechatInvite.FIELD_SENCE_STR, senceStr);
        return this.findOne(example);
    }

    private CreateTicketResult getTicket(String mpId, long expiredSeconds, String type, String senceStr) {
        ReqCreateTicket reqCreateTicket = new ReqCreateTicket();
        reqCreateTicket.setExpireSeconds(expiredSeconds);
        reqCreateTicket.setActionName(type);
        ActionInfo actionInfo = new ActionInfo();
        Scene sence = new Scene();
        sence.setSceneId(0);
        sence.setSceneStr(senceStr);
        actionInfo.setScene(sence);
        reqCreateTicket.setActionInfo(actionInfo);
        CreateTicketResult result = WXContext.getAccountInvoker().createTicket(mpId, reqCreateTicket);
        if(result.getErrcode().intValue() == WXResponseCode.CODE_0_SUCCESS) {
            return result;
        }else {
            throw new IllegalStateException(result.getErrmsg());
        }
    }

    /**
     * 分享是否过期
     * @param wechatInvite
     * @return
     */
    private boolean isExpired(WechatInvite wechatInvite) {
        if(wechatInvite.getTime().getTime() + wechatInvite.getExpiredSeconds() * 1000 <= System.currentTimeMillis() - 60 * 1000) {
            return true;
        }
        return false;
    }

}
